#!/usr/bin/env python

'''RWB - the Robot Framework Workbench

Use the argument "--help" to see a list of command line arguments
'''

import logging
import os
import sys
import optparse
import wx

# make sure whatever directory this file is in, is in the path
module_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if module_dir not in sys.path:
    sys.path.insert(0,module_dir)

try:
    # this file doesn't require robot, but if it's not available
    # this is a good time to learn that.
    import robot
    import firebrick
    import rwb
except ImportError, e:
    print "unable to import required libraries\n", e
    sys.exit(1)
    
import rwb.plugins
PLUGINPATH = ("rwb.plugins",)
#PLUGINPATH = (os.path.join(os.path.dirname(__file__),"plugins"),)
REQUIRED_WX_VERSION = (2,8,10)
REQUIRED_PY_VERSION = (2,5)
DEFAULT_PORT = 8910
DEFAULT_LOG_LEVEL = "WARNING"
DEFAULT_LOG_FILE = "-"

def main():

    rwb.opt, rwb.args = parse_arguments()
    initialize_logging()
    check_environment()

    settings_dir = os.path.expanduser("~/.rwb")
    if not os.path.exists(settings_dir):
        os.makedirs(settings_dir)
    settings_file = os.path.join(settings_dir,"settings.cfg")
    rwb.RWBApp(settings=settings_file, pluginpath = PLUGINPATH)

    ##
    # should the rest of this method be moved to RWBApp.OnInit?
    ##

    rwb.app.Register(rwb.GeneralPreferencesPanel)

    # by putting this here rather than in the RWBApp constructor
    # paves the way to create a headless instance of the app
    # for some level of testing (opening files and whatnot).
    # Will I ever do that? <shrug>
    rwb.windows = [rwb.app.NewWindow()]

    for path in rwb.args:
        if os.path.exists(path):
            wx.CallAfter(rwb.app.Open, path)
        else:
            rwb.log.warning("%s: file not found" % path)

    wx.GetApp().MainLoop()

def parse_arguments():
    p = optparse.OptionParser()
    p.add_option("-p", "--port", 
                 help="port to use to communicate with a running test " +
                 "(default: %s)" % DEFAULT_PORT)
    p.add_option("-l", "--log-level",
                 help="set log level (must be one of DEBUG, " +
                 "INFO, WARNING, ERROR, CRITICAL) " +
                 "(default: %s)" % DEFAULT_LOG_LEVEL)
    p.add_option("-L", "--log-file",
                 help="log file (default: stderr).")
    p.add_option("-D", "--debug-mode", action="store_true",
                 help="same as --log-level=DEBUG --log-file=-")
    p.set_defaults(port=DEFAULT_PORT)
    p.set_defaults(log_level = DEFAULT_LOG_LEVEL)
    p.set_defaults(log_file = DEFAULT_LOG_FILE)
    p.set_defaults(debug_mode = False)
    p.set_usage("Usage: %prog [options] [test-suite]")
    opt,args = p.parse_args()

    return opt, args

def initialize_logging():
    '''Initialize application logger'''
    # mode of "w", so it always overwrites existing logs
    if rwb.opt.debug_mode:
        handler = logging.StreamHandler(sys.stderr)
        rwb.opt.log_level = "DEBUG"
    else:
        if rwb.opt.log_file == "-":
            handler = logging.StreamHandler(sys.stderr)
        else:
            handler = logging.FileHandler(rwb.opt.log_file, "w")

    formatter = logging.Formatter("%(levelname)s: %(module)s.%(funcName)s: %(message)s")
    handler.setFormatter(formatter)

    rwb.log = logging.getLogger()
    rwb.log.setLevel(getattr(logging, rwb.opt.log_level, getattr(logging, DEFAULT_LOG_LEVEL)))
    rwb.log.addHandler(handler)

    # the idea behind the win_handler is to provide a way to display
    # log messages in the GUI. At the moment this is half-baked. Who
    # owns the window? When is it created? Should it show info messages,
    # or only warnings and errors?
    # win_handler = WindowLogger()
    # win_handler.setFormatter(formatter)
    # win_handler.setLevel(logging.WARNING)
    # rwb.log.addHandler(win_handler)

    rwb.log.debug("log initialized; level=%s" % rwb.log.getEffectiveLevel())

        
class WindowLogger(logging.Handler):
    def __init__(self, ctrl=None):
        logging.Handler.__init__(self)
        self.ctrl = ctrl
    def emit(self, record):
        print "*****", self.format(record)+"\n"
#        self.ctrl.AppendText(self.format(record)+"\n") 

def check_environment():
    '''Verifies that the correct version of python and wxPython is being used'''

    try:
        import wx
    except ImportError, e:
        rwb.log.critical("unable to load wxPython", exc_info=e)
        sys.stderr.write("Epic fail, wxPython is required but cannot be loaded\n")
        sys.exit(1)

    violations = []
    if wx.VERSION < REQUIRED_WX_VERSION:
        violations.append("wxPython: Running: %s Required: %s" % 
                              (_version(REQUIRED_WX_VERSION), _version(wx.VERSION)))

    if sys.version_info < REQUIRED_PY_VERSION:
        violations.append("python: Required: %s Using: %s" %
                          (_version(REQUIRED_PY_VERSION), _version(sys.version_info)))

    if len(violations) > 0:
        plural = "s" if len(violations) > 1 else ""
        message = "You do not have the minimum required version of the following software package%s:\n\n" % plural
        for violation in violations:
            message += violation + "\n"
        show_fatal_dialog(message)

    try:
        import robot
    except ImportError, e:
        message = "Unable to import the robot framework library\n"
        show_fatal_dialog(message, e)

def _version(version_tuple):
    return ".".join([str(number) for number in version_tuple])

def show_fatal_dialog(message, exc_info = None):
    '''Show a dialog with the given message, then exit'''

    import wx
    caption="RWB Startup Error"
    rwb.log.critical(message, exc_info=exc_info)
    app = wx.App()
    dialog = wx.MessageDialog(None, message, caption, style=wx.OK|wx.ICON_INFORMATION)
    dialog.ShowModal()
    app.MainLoop()
    sys.exit(1)

if __name__ == "__main__":
    main()




    
